package cn.vc.auth.service;

import cn.vc.auth.entity.po.AuthorityLevel;
import cn.vc.auth.entity.po.Relation;
import cn.vc.auth.entity.po.VUser;
import cn.vc.auth.mapper.UserMapper;
import cn.vc.auth.util.DateUtil;
import cn.vc.auth.util.SecurityUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.xml.crypto.Data;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class UserService extends ServiceImpl<UserMapper, VUser> {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Resource
    private StringRedisTemplate stringRedisTemplate;



    /**
     * <h2>添加用户</h2>
     * @param vUser
     * @return
     */
    public boolean insert(VUser vUser) {
        //查询最大ID
        Long maxId = userMapper.selectMaxId();
        if (maxId == null) maxId = 10000000000L;//如果为空说明无用户，自动赋值为0
        vUser.setAccount(this.getAccount(maxId+1));//通过ID获取账号
        vUser.setPassword(passwordEncoder.encode(vUser.getPassword()));//加密密码
        vUser.setAvatarUrl("/userstatic/head.jpeg");
        vUser.setSignature("这个人很神秘，什么都没有写");
        return userMapper.insert(vUser)==1;
    }
    /**
     * 新增粉丝
     * @param userId
     */
    public void attention(Long userId) {
        VUser VUser = userMapper.selectById(userId);
        if (VUser ==null) return;
        VUser.setFansNum(VUser.getFansNum()+1);
        userMapper.updateById(VUser);
    }
    /**
     * 减少粉丝
     * @param userId
     */
    public void noAttention(Long userId) {
        VUser VUser = userMapper.selectById(userId);
        if (VUser ==null) return;
        VUser.setFansNum(VUser.getFansNum()==0?0: VUser.getFansNum()-1);
        userMapper.updateById(VUser);
    }



    /**
     * <h2>删除用户</h2>
     * @param id
     * @return
     */
    public boolean deleteById(Long id) {
        return userMapper.deleteById(id)==1;
    }



    /**
     * 通过ID查询
     * @param id
     * @param al 查询权限
     */
    public VUser selectById(Long id, AuthorityLevel al) {
        switch (al) {
            case ROOT:
                return userMapper.selectById(id);
            case TOURIST: {
                LambdaQueryWrapper<VUser> lqw = new LambdaQueryWrapper<>();
                lqw.eq(VUser::getId, id).eq(VUser::getDeleted, 0);
//                        .select(VUser::getId, VUser::getEmail, VUser::getUsername, VUser::getAvatarUrl, VUser::getAccount, VUser::getLv, VUser::getExp, VUser::getBlueV, VUser::getShopId, VUser::getFollowersNum, VUser::getFansNum);
                VUser vUser = userMapper.selectOne(lqw);
                if (vUser==null) return null;
                vUser.setName(null);
                vUser.setPassword(null);
                vUser.setSetTime(null);
                vUser.setDeleted(null);
                return vUser;
            }
            default:
                return null;
        }
    }
    /**
     * 通过ID查询
     * @param id
     * @param bo 是否查询全部信息（默认为false）
     */
    public VUser selectById(Long id, boolean bo) {
        VUser vUser = null;
        String userJSON = stringRedisTemplate.opsForValue().get(SecurityUtil.AUTH_USER_KEY+id);
        if (userJSON==null) {
            vUser = userMapper.selectById(id);
            // 如果会员过期则设为普通会员
            if (vUser.getMember()!=0&&timeIsFormerly(vUser.getMemberExpirationTime())) {
                vUser.setMember(0);
                userMapper.updateById(vUser);
            }
            if (!bo) vUser.setPassword(null);
            // 存入缓存
            stringRedisTemplate.opsForValue().set(SecurityUtil.AUTH_USER_KEY +id, JSON.toJSONString(vUser), 30, TimeUnit.SECONDS);
        } else {
            vUser = JSON.parseObject(userJSON, VUser.class);
        }
        return vUser;
    }
    public List<VUser> selectByIds(List<Long> ids) {
        if (ids==null || ids.isEmpty()) return null;
        return userMapper.selectByIds(ids);
    }
    /**
     * 通过token查询用户
     */
    public VUser selectByToken(String token) {
        String userJson = stringRedisTemplate.opsForValue().get(token);
        if (userJson==null) return null;
        return JSON.parseObject(userJson, VUser.class);
    }
    /**
     * <h2>通过account查询用户</h2>
     * @param account
     * @return
     */
    public VUser selectByAccount(String account) {
        LambdaQueryWrapper<VUser> lqw = new LambdaQueryWrapper<>();
        lqw.eq(VUser::getAccount, account);
        return userMapper.selectOne(lqw);
    }
    /**
     * 通过Email查询用户
     * @param email
     * @return
     */
    public VUser selectByEmail(String email) {
        LambdaQueryWrapper<VUser> lqw = new LambdaQueryWrapper<>();
        lqw.eq(VUser::getEmail, email);
        return userMapper.selectOne(lqw);
    }
    /**
     * <h2>查询账号密码</h2>
     * @param account
     * @param password
     * @param isEncrypt 是否加密
     * @return
     */
    public VUser selectByAccountAndPassword(String account, String password, boolean isEncrypt) {
        LambdaQueryWrapper<VUser> lqw = new LambdaQueryWrapper<>();
        lqw.eq(VUser::getAccount, account);
        VUser VUser = userMapper.selectOne(lqw);
        if (VUser !=null) {
            //判断密码是否相同
            boolean bo = isEncrypt?password.equals(VUser.getPassword()):passwordEncoder.matches(password, VUser.getPassword());
            return bo? VUser :null;
        } else return null;
    }
    /**
     * <h2>查询邮箱密码</h2>
     * @param email
     * @param password
     * @return
     */
    public VUser selectByEmailAndPassword(String email, String password) {
        LambdaQueryWrapper<VUser> lqw = new LambdaQueryWrapper<>();
        lqw.eq(VUser::getEmail, email);
        VUser VUser = userMapper.selectOne(lqw);
        return VUser != null && passwordEncoder.matches(password, VUser.getPassword())? VUser :null;
    }
    /**
     * <h2>通过用户名、账号、密码、邮箱查询用户信息</h2>
     * @param username
     * @param account
     * @param password
     * @param email
     * @return
     */
    public VUser selectByUsernameAndAccountAndPasswordAndEmail(String username, String account, String password, String email) {
        LambdaQueryWrapper<VUser> lqw = new LambdaQueryWrapper<>();
        lqw.eq(VUser::getUsername, username).eq(VUser::getAccount, account).eq(VUser::getEmail, email);
        VUser VUser = userMapper.selectOne(lqw);
        //user不为空且密码相同
        if (VUser !=null && passwordEncoder.matches(password, VUser.getPassword())) {
            return VUser;
        } else return null;
    }



    /**
     * <h2>修改用户</h2>
     * @param identifier 修改字段标识符
     * @param newVUser 需要修改的用户信息
     * @return
     */
    public boolean alter(String identifier, VUser newVUser) {
        VUser oldVUser = this.selectByAccount(newVUser.getAccount());
        if (oldVUser == null) return false;
        LambdaQueryWrapper<VUser> lqw = new LambdaQueryWrapper<>();
        //判断需要修改的字段名
        switch (identifier) {
            case "standing": {
                return false;
            }//修改身份信息
            case "phone": {
                return false;
            }//修改手机号
            case "email": {
                return false;
            }//修改电子邮箱
            //修改密码
            case "password": {
                if (oldVUser.getPassword().equals(newVUser.getPassword())) {

                } else return false;
            }
            default: return false;
        }
    }
    /**
     * <h2>修改用户名</h2>
     * @param account
     * @param name
     * @return
     */
    public boolean updateUsername(String account, String name) {
        return userMapper.updateUsername(account, name)==1;
    }
    /**
     * 修改头像url
     */
    public boolean updateAvatarUrl(Long userId, String avatarUrl) {
        return userMapper.updateAvatarUrlById(userId, avatarUrl)==1;
    }
    /**
     * <h2>修改密码</h2>
     * @param account
     * @param oldPassword
     * @param newPassword
     * @return
     */
    public boolean updatePassword(String account, String oldPassword, String newPassword) {
        VUser VUser = userMapper.selectAccount(account);
        if (VUser.getPassword().equals(oldPassword)) {
            VUser.setPassword(passwordEncoder.encode(newPassword));
            return userMapper.updateById(VUser)==1;
        } else return false;
    }
    /**
     * <h2>通过id修改实名信息</h2>
     * @param id
     * @param name
     * @param idNum
     * @return
     */
    public boolean updateNameAndIdNum(Long id, String name, String idNum) {
        VUser VUser = userMapper.selectById(id);
        VUser.setName(name);
        VUser.setIdNum(idNum);
        return userMapper.updateById(VUser)==1;
    }

    /**
     * 购买会员
     * @param id 购买用户
     * @param member 会员类型
     * @param months 会员时长
     */
    public void butMember(Long id, int member, int months) {
        VUser vUser = selectById(id, false);
        if (vUser==null) return;
        Timestamp oldTimestamp = vUser.getMemberExpirationTime();
        Timestamp timestamp = null;
        // 为空或者已经过期则时长从现在开始计时
        if (oldTimestamp==null||timeIsFormerly(oldTimestamp)) {
            timestamp = new Timestamp(DateUtil.getNextMonth(DateUtil.getNowDate(), months).getTime());
        }
        // 未过期则加上时长
        else {
            timestamp = new Timestamp(DateUtil.getNextMonth(oldTimestamp, months).getTime());
        }
        // 更新数据库
        LambdaUpdateWrapper<VUser> luw = new LambdaUpdateWrapper<>();
        luw.eq(VUser::getId, id)
                // 更新会员级别
                .set(VUser::getMember, member)
                // 更新会员时间
                .set(VUser::getMemberExpirationTime, timestamp);
        userMapper.update(null, luw);
    }



    /**
     * 通过ID转换为账号
     * @param id
     * @return
     */
    String getAccount(Long id) {
        String str = id.toString();
        StringBuilder acc = new StringBuilder();
        for (int i = 1; i < 12-str.length(); i++) {
            acc.insert(0,"0");
        }
        acc.append(str);
        return acc.toString();
    }

    /**
     * 时间是否过去
     * @param timestamp 需要判断的时间
     * @return
     */
    boolean timeIsFormerly(Timestamp timestamp) {
        if (timestamp==null) return true;
        boolean bo = timestamp.before(new Date(System.currentTimeMillis()));
        return bo;
//        long oldTime = timestamp.getTime();
//        long nowTime = System.currentTimeMillis();
//        return oldTime < nowTime;
    }
}
